#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QtMath>
#include "RawImage.h"

RawImage::RawImage(const QString &strRaw) : m_iWWidth(0), m_iWCenter(0), m_fGamma(1.f),
	m_iWindowingMin(0), m_iWindowingMax(0)
{
	this->loadRaw(strRaw);
}

void RawImage::setWindowing(int width, int center)
{
	qDebug() << m_iWWidth << m_iWCenter << width << center;
	if(!(m_iWWidth == width && m_iWCenter == center))
	{
		m_iWWidth = width;
		m_iWCenter = center;
		this->applyProcess();
	}
	else
	{
		m_iWWidth = width;
		m_iWCenter = center;
	}
	qDebug() << m_iWWidth << m_iWCenter << width << center;
}

void RawImage::setGamma(int gamma)
{
	m_fGamma = gamma / 10;

	this->applyProcess();
}

const QMap<int, int> RawImage::histogramData()
{
	return m_histogramData;
}

void RawImage::loadRaw(const QString &strRaw)
{
	QFile file(strRaw);
	qDebug() << QFileInfo(strRaw).absoluteFilePath();

	if(file.exists() && QFileInfo(file).isFile())
	{
		m_iWidth = (int)qSqrt(file.size() / 2) + 1;
		m_iHeight = m_iWidth - 1;
		qDebug() << "[image size]" << m_iWidth << m_iHeight;
		file.open(QIODevice::ReadOnly);

		QByteArray ba = file.readAll();

		file.close();

		QImage::operator =(QImage(m_iWidth, m_iHeight, QImage::Format_RGB32));

		m_vec.clear();

		for (int var = 0; var < ba.count(); var += 2)
		{
			short raw;
			char low = ba.at(var);
			char high = ba.at(var + 1);

			raw = high;
			raw = ((raw & 0x3f) << 8) | (low & 0xff);
			m_vec << raw;
		}

		foreach (short data, m_vec)
		{
			m_histogramData[(int)data] = m_histogramData[(int)data] + 1;
		}

		if(m_histogramData.count() > 0)
		{
			QList<int> keys = m_histogramData.keys();

			qSort(keys);
			m_iWindowingMin = keys.first();
			m_iWindowingMax = keys.last();
			m_iWWidth = m_iWindowingMax - m_iWindowingMin;
			m_iWCenter = m_iWindowingMin + m_iWWidth / 2;
		}
		else {}

		this->applyProcess();
	}
}

const QList<int> RawImage::profileData(const QList<QPoint> &listPoint) const
{
	QList<int> profile;

	foreach (QPoint pt, listPoint)
	{
		qDebug() << pt << m_iWidth << m_iHeight;
		if(pt.x() < 0 || pt.x() > m_iWidth - 1 || pt.y() < 0 || pt.y() > m_iHeight - 1) profile << 0;
		else profile << (int)m_vec.at(pt.y() * m_iWidth + pt.x());
	}

	return profile;
}

void RawImage::windowing(int &iWWMax, int &iWWMin, int &iWidth, int &iCenter) const
{
	iWWMax = m_iWindowingMax;
	iWWMin = m_iWindowingMin;
	iWidth = m_iWWidth;
	iCenter = m_iWCenter;
}

void RawImage::applyProcess()
{
	int half(m_iWWidth / 2);
	int min(m_iWCenter - half);
	int max(m_iWCenter + half);
	float invGamma = 1 / m_fGamma;

	for (int height = 0; height < m_iHeight; ++height)
	{
		for (int width = 0; width < m_iWidth; ++width)
		{
			short raw = qBound((short)min, m_vec.at(height * m_iWidth + width), (short)max);
			QRgb *rgb = (QRgb*)this->scanLine(height);
			uchar converted(1.0f * (raw - min) / m_iWWidth * 255);

			converted = qPow(converted / 255.f, invGamma) * 255;

			rgb += width;
			*rgb = qRgb(converted, converted, converted);
		}
	}
}
